﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cesave.Domain.PermisosModule.Entities;
using System.ComponentModel;
using Cesave.Application.Permisos.ServiceAgent;
using System.Windows.Forms;
using Cesave.Domain.Core.Entities;

namespace Cesave.Presentation.Permisos.WinForms.Client.ViewModels.Catalogs.Areas
{
    /// <summary>
    /// Sección del manejo de áreas de influencia.
    /// </summary>
    public partial class AreasViewModel
    {
        #region Private properties

        /// <summary>
        /// Lista de áreas de influencia.
        /// </summary>
        private List<Area> _areas;

        /// <summary>
        /// Área de influencia seleccionada.
        /// </summary>
        private Area _area;

        #endregion

        #region Public properties

        /// <summary>
        /// Lista de áreas de influencia.
        /// </summary>
        public List<Area> Areas
        {
            get
            {
                return _areas;
            }
            private set
            {
                _areas = value;
                if (_areas != null)
                    RaisePropertyChanged("Areas");
            }
        }

        /// <summary>
        /// Área de influencia seleccionada.
        /// </summary>
        public Area Area
        {
            get
            {
                return _area;
            }
            private set
            {
                _area = value;
                if (_area != null)
                    RaisePropertyChanged("Area");
            }
        }

        /// <summary>
        /// Determina si ya se ha seleccionado un área de influencia.
        /// </summary>
        public bool IsAreaReady
        {
            get
            {
                return Area != null;
            }
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Carga las áreas de influencia de la junta actual.
        /// </summary>
        private void LoadAreas()
        {
            StartWaiting();
            using (BackgroundWorker worker = new BackgroundWorker())
            {
                worker.DoWork += (sender, e) =>
                {
                    using (PermisosModuleServiceWrapper service = new PermisosModuleServiceWrapper())
                    {
                        e.Result = service.FindAreasByJuntaArea(_pusSettings.Junta.JuntaGuid);
                    }
                };
                worker.RunWorkerCompleted += (sender, e) =>
                {
                    EndWaiting();
                    if (!e.Cancelled && e.Error == null)
                        Areas = e.Result as List<Area>;
                    else if (e.Error != null)
                        ShowMessage(e.Error.Message);
                };
                worker.WorkerSupportsCancellation = true;
                worker.RunWorkerAsync();
            }
        }

        #endregion

        #region Event methods

        /// <summary>
        /// Envía los cambios realizados en las áreas de influencia a la base de datos.
        /// </summary>
        private void SaveAreas(object s, EventArgs args)
        {
            StartWaiting();
            using (BackgroundWorker worker = new BackgroundWorker())
            {
                worker.DoWork += (sender, e) =>
                {
                    using (PermisosModuleServiceWrapper service = new PermisosModuleServiceWrapper())
                    {
                        Areas.ForEach(a =>
                        {
                            if (a.ChangeTracker.State == ObjectState.Added)
                                service.AddArea(a);
                            else if (a.ChangeTracker.State == ObjectState.Modified)
                                service.ChangeArea(a);
                            a.AcceptChanges();
                        });
                    }
                };
                worker.RunWorkerCompleted += (sender, e) =>
                {
                    EndWaiting();
                    if (!e.Cancelled && e.Error == null)
                    {
                        SaveAreaSecciones(s, args);
                    }
                    else if (e.Error != null)
                        ShowMessage(e.Error.Message);
                };
                worker.WorkerSupportsCancellation = true;
                worker.RunWorkerAsync();
            }
        }

        /// <summary>
        /// Agrega una nueva área de influencia.
        /// </summary>
        private void AddNewArea(object sender, EventArgs e)
        {
            _view.areasBindingSource.AddingNew += AddingNewArea;
            _view.areasBindingSource.AddNew();
        }

        /// <summary>
        /// Se ejecuta al agregar una nueva área de influencia.
        /// </summary>
        private void AddingNewArea(object sender, AddingNewEventArgs e)
        {
            Area = new Area
            {
                AreaGuid = Guid.NewGuid(),
                AreaId = 0,
                JuntaGuid = _pusSettings.Junta.JuntaGuid,
                JuntaId = _pusSettings.Junta.JuntaId,
                Letra = string.Empty,
                MostrarEnExpedicion = true,
                Nombre = string.Empty,
                Status = true,
            };
            Area.MarkAsAdded();
            e.NewObject = Area;
            FocusDefaultControl();
        }

        /// <summary>
        /// Identifica el área de influencia seleccionada en la vista.
        /// </summary>
        private void SetCurrentArea(object sender, EventArgs e)
        {
            BindingSource bindingSource = sender as BindingSource;
            if (bindingSource != null && bindingSource.Current != null)
                Area = bindingSource.Current as Area;
        }

        /// <summary>
        /// Se ejecuta cuando la propiedad Areas cambia de valor.
        /// </summary>
        private void OnAreasPropertyChanged()
        {
            _view.areasBindingSource.DataSource = Areas;
            _view.areasBindingSource.CurrentChanged += SetCurrentArea;
            SetCurrentArea(_view.areasBindingSource, new EventArgs());
        }

        /// <summary>
        /// Ocurre cuando la propiedad Area cambia de valor.
        /// </summary>
        private void OnAreaPropertyChanged()
        {
            Area.MarkAsModified();
            LoadAreaSecciones();
        }

        #endregion

    }
}